// webgl/webgl_raycaster_texture.js
import {document,window,requestAnimationFrame,cancelAnimationFrame,Event,core,performance} from 'dhtml-weixin';
import * as THREE from '../three/Three.js';
import  { GUI } from './jsm/libs/lil-gui.module.min.js';
var requestId
Page({
	   
         onUnload() {
	   		cancelAnimationFrame(requestId, this.canvas)
this.worker && this.worker.terminate()
		setTimeout(() => {
			if (this.renderer instanceof THREE.WebGLRenderer) {
				this.renderer.dispose()
				this.renderer.forceContextLoss()
				this.renderer.context = null
				this.renderer.domElement = null
				this.renderer = null
			}
		}, 0)
        
	},
         webgl_touch(e) {
        const web_e = Event.fix(e)
        //window.dispatchEvent(web_e)
        //document.dispatchEvent(web_e)
        this.canvas.dispatchEvent(web_e)
    },
async onLoad() {
        const canvas3d = this.canvas =await document.createElementAsync("canvas","webgl")
        var canvas
var that = this
        const WRAPPING = {
            'RepeatWrapping': THREE.RepeatWrapping,
            'ClampToEdgeWrapping': THREE.ClampToEdgeWrapping,
            'MirroredRepeatWrapping': THREE.MirroredRepeatWrapping
        };

        const params = {
            wrapS: THREE.RepeatWrapping,
            wrapT: THREE.RepeatWrapping,
            offsetX: 0,
            offsetY: 0,
            repeatX: 1,
            repeatY: 1,
            rotation: 0,
        };


        function CanvasTexture( parentTexture ) {

            this._canvas = document.createElement( 'canvas' );
            this._canvas.width = this._canvas.height = 1024;
            this._context2D = this._canvas.getContext( '2d' );

            if ( parentTexture ) {

                this._parentTexture.push( parentTexture );
                core.Canvas.toImage(canvas3d,this._canvas).then( image=> parentTexture.image=  image);

            }

            const that = this;
            this._background = document.createElement( 'img' );
            this._background.addEventListener( 'load', function () {

                that._canvas.width = that._background.naturalWidth;
                that._canvas.height = that._background.naturalHeight;

                that._crossRadius = Math.ceil( Math.min( that._canvas.width, that._canvas.height / 30 ) );
                that._crossMax = Math.ceil( 0.70710678 * that._crossRadius );
                that._crossMin = Math.ceil( that._crossMax / 10 );
                that._crossThickness = Math.ceil( that._crossMax / 10 );

                that._draw();

            } );
            this._background.crossOrigin = '';
            this._background.src = 'textures/uv_grid_opengl.jpg';

            this._draw();

        }


        CanvasTexture.prototype = {

            constructor: CanvasTexture,

            _canvas: null,
            _context2D: null,
            _xCross: 0,
            _yCross: 0,

            _crossRadius: 57,
            _crossMax: 40,
            _crossMin: 4,
            _crossThickness: 4,

            _parentTexture: [],

            addParent:async function ( parentTexture ) {

                if ( this._parentTexture.indexOf( parentTexture ) === - 1 ) {

                    this._parentTexture.push( parentTexture );
                    parentTexture.image = await core.Canvas.toImage(canvas3d,this._canvas);

                }

            },

            setCrossPosition: function ( x, y ) {

                this._xCross = x * this._canvas.width;
                this._yCross = y * this._canvas.height;

                this._draw();

            },

            _draw: function () {

                if ( ! this._context2D ) return;

                this._context2D.clearRect( 0, 0, this._canvas.width, this._canvas.height );

                // Background.
               // this._context2D.drawImage( this._background, 0, 0 );

                // Yellow cross.
                this._context2D.lineWidth = this._crossThickness * 3;
                this._context2D.strokeStyle = '#FFFF00';

                this._context2D.beginPath();
                this._context2D.moveTo( this._xCross - this._crossMax - 2, this._yCross - this._crossMax - 2 );
                this._context2D.lineTo( this._xCross - this._crossMin, this._yCross - this._crossMin );

                this._context2D.moveTo( this._xCross + this._crossMin, this._yCross + this._crossMin );
                this._context2D.lineTo( this._xCross + this._crossMax + 2, this._yCross + this._crossMax + 2 );

                this._context2D.moveTo( this._xCross - this._crossMax - 2, this._yCross + this._crossMax + 2 );
                this._context2D.lineTo( this._xCross - this._crossMin, this._yCross + this._crossMin );

                this._context2D.moveTo( this._xCross + this._crossMin, this._yCross - this._crossMin );
                this._context2D.lineTo( this._xCross + this._crossMax + 2, this._yCross - this._crossMax - 2 );

                this._context2D.stroke();

                for ( let i = 0; i < this._parentTexture.length; i ++ ) {

                    this._parentTexture[ i ].needsUpdate = true;

                }

            }

        };

        const width = window.innerWidth;
        const height = window.innerHeight;

        let planeTexture, cubeTexture, circleTexture;

        let container;

        let camera, scene, renderer;

        const raycaster = new THREE.Raycaster();
        const mouse = new THREE.Vector2();
        const onClickPosition = new THREE.Vector2();

    await    init();
        render();

      async  function init() {

            container = document.getElementById( 'container' );

            scene = new THREE.Scene();
            scene.background = new THREE.Color( 0xeeeeee );

            camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 );
            camera.position.x = - 30;
            camera.position.y = 40;
            camera.position.z = 50;
            camera.lookAt( scene.position );

            renderer = that.renderer = new THREE.WebGLRenderer({canvas:canvas3d});
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( width, height );
            container.appendChild( renderer.domElement );

            // A cube, in the middle.
            cubeTexture = new THREE.Texture( undefined, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping );
            canvas = new CanvasTexture(cubeTexture);
            const cubeMaterial = new THREE.MeshBasicMaterial( { map: cubeTexture } );
            const cubeGeometry = new THREE.BoxGeometry( 20, 20, 20 );
            let uvs = cubeGeometry.attributes.uv.array;
            // Set a specific texture mapping.
            for ( let i = 0; i < uvs.length; i ++ ) {

                uvs[ i ] *= 2;

            }

            const cube = new THREE.Mesh( cubeGeometry, cubeMaterial );
            cube.position.x = 4;
            cube.position.y = - 5;
            cube.position.z = 0;
            scene.add( cube );

            // A plane on the left

            planeTexture = new THREE.Texture( undefined, THREE.UVMapping, THREE.MirroredRepeatWrapping, THREE.MirroredRepeatWrapping );
            canvas.addParent( planeTexture );
            const planeMaterial = new THREE.MeshBasicMaterial( { map: planeTexture } );
            const planeGeometry = new THREE.PlaneGeometry( 25, 25, 1, 1 );
            uvs = planeGeometry.attributes.uv.array;

            // Set a specific texture mapping.

            for ( let i = 0; i < uvs.length; i ++ ) {

                uvs[ i ] *= 2;

            }

            const plane = new THREE.Mesh( planeGeometry, planeMaterial );
            plane.position.x = - 16;
            plane.position.y = - 5;
            plane.position.z = 0;
            scene.add( plane );

            // A circle on the right.

            circleTexture = new THREE.Texture( undefined, THREE.UVMapping, THREE.RepeatWrapping, THREE.RepeatWrapping );
          await  canvas.addParent( circleTexture );
            const circleMaterial = new THREE.MeshBasicMaterial( { map: circleTexture } );
            const circleGeometry = new THREE.CircleGeometry( 25, 40, 0, Math.PI * 2 );
            uvs = circleGeometry.attributes.uv.array;

            // Set a specific texture mapping.

            for ( let i = 0; i < uvs.length; i ++ ) {

                uvs[ i ] = ( uvs[ i ] - 0.25 ) * 2;

            }

            const circle = new THREE.Mesh( circleGeometry, circleMaterial );
            circle.position.x = 24;
            circle.position.y = - 5;
            circle.position.z = 0;
            scene.add( circle );

            window.addEventListener( 'resize', onWindowResize );
            container.addEventListener( 'mousemove', onMouseMove );

            //

            const gui = new GUI();
            gui.title( 'Circle Texture Settings' );

            gui.add( params, 'wrapS', WRAPPING ).onChange( setwrapS );
            gui.add( params, 'wrapT', WRAPPING ).onChange( setwrapT );
            gui.add( params, 'offsetX', 0, 5 );
            gui.add( params, 'offsetY', 0, 5 );
            gui.add( params, 'repeatX', 0, 5 );
            gui.add( params, 'repeatY', 0, 5 );
            gui.add( params, 'rotation', 0, 2 * Math.PI );
            gui.open();

        }

        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        function onMouseMove( evt ) {

            evt.preventDefault();

            const array = getMousePosition( container, evt.clientX, evt.clientY );
            onClickPosition.fromArray( array );

            const intersects = getIntersects( onClickPosition, scene.children );

            if ( intersects.length > 0 && intersects[ 0 ].uv ) {

                const uv = intersects[ 0 ].uv;
                intersects[ 0 ].object.material.map.transformUv( uv );
                canvas.setCrossPosition( uv.x, uv.y );

            }

        }

        function getMousePosition( dom, x, y ) {

            const rect = dom.getBoundingClientRect();
            return [ ( x - rect.left ) / rect.width, ( y - rect.top ) / rect.height ];

        }

        function getIntersects( point, objects ) {

            mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );

            raycaster.setFromCamera( mouse, camera );

            return raycaster.intersectObjects( objects, false );

        }
var count=0
        function render() {
if(count++>10){
    return
}
            requestId = requestAnimationFrame( render );

            // update texture parameters

            circleTexture.offset.x = params.offsetX;
            circleTexture.offset.y = params.offsetY;
            circleTexture.repeat.x = params.repeatX;
            circleTexture.repeat.y = params.repeatY;
            circleTexture.rotation = params.rotation;

            //

            renderer.render( scene, camera );

        }

        function setwrapS( value ) {

            circleTexture.wrapS = value;
            circleTexture.needsUpdate = true;

        }

        function setwrapT( value ) {

            circleTexture.wrapT = value;
            circleTexture.needsUpdate = true;

        }
    }
})